package com.wanyu.video.nio.chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class GroupChatServer {


    private Selector selector;

    private ServerSocketChannel serverSocketChannel;

    private static final int PORT = 6666;



    public GroupChatServer(){
        try {

            // 初始化选择器
            selector = Selector.open();
            // 初始化ServerSocketChannel
            serverSocketChannel = ServerSocketChannel.open();
            // 绑定监听端口
            serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
            // 设置非阻塞
            serverSocketChannel.configureBlocking(false);
            // 注册到Selector
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    public void listen(){

        try {
            while(true){
                //
                int count = selector.select();
                if(count > 0){
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while(iterator.hasNext()){
                        
                        SelectionKey selectionKey = iterator.next();
                        if(selectionKey.isAcceptable()){
                            // 这里需要注意，根据selectionKey获取对应的注册的通道，
                            ServerSocketChannel currentServerChannel  = (ServerSocketChannel) selectionKey.channel();
                            SocketChannel socketChannel = currentServerChannel.accept();
                            socketChannel.configureBlocking(false);
                            // 将当前socketChannel注册到当前selectionKey对应的Selector上
                            socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ);
                            System.out.println(socketChannel.getRemoteAddress() + " 上线");
                        }
                        // 如果通道可以读
                        if(selectionKey.isReadable()){
                            readData(selectionKey);
                        }

                        // 处理完当前通道后移除当前key， 防止重复读取数据
                        iterator.remove();
                    }
                }else{
                    System.out.println("等待客户端连接");
                }

            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void readData(SelectionKey key){
        SocketChannel channel = null;
        try {
            // 获取客户端channel
            channel =  (SocketChannel)key.channel();

            ByteBuffer buffer = ByteBuffer.allocate(1024);
            // 把客户端传输的消息写到channel读取出来并写入缓冲区
            int read = channel.read(buffer);

            if (read > 0){
                String msg = new String(buffer.array());
                // 向其他客户端发送消息
                sendInfoToOtherClient(msg, channel);
            }

        }catch (IOException ioe){
            try {
                System.out.println(channel.getRemoteAddress() + "离线了");
                key.cancel();
                channel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    // 转发消息给其他客户端
    private void sendInfoToOtherClient(String msg, SocketChannel self) throws IOException {
        System.out.println("服务端转发消息中");
        for (SelectionKey key : selector.keys()) {

            // 取出所有对应的通道
            Channel targetChannel = key.channel();
            if(targetChannel instanceof SocketChannel && targetChannel != self){
                // 将缓冲区中的数据写入到通道中
                ((SocketChannel) targetChannel).write(ByteBuffer.wrap(msg.getBytes()));
            }
        }
        
    }

    public static void main(String[] args) {
        GroupChatServer groupChatServer = new GroupChatServer();
        groupChatServer.listen();
    }
}
